import { getCurrentScope, onScopeDispose } from 'vue-demi'
import { _Method } from './types'

export const noop = () => {}

/**
 * 添加订阅
 * - 如果不是独立的，而且是在组件中进行了订阅，则在组件卸载时自动移除（通过组件的 onScopeDispose 实现）
 * @param subscriptions 保存订阅事件回调的集合
 * @param callback 函数，待添加的订阅事件回调
 * @param detached 是否为独立的，true=不会自动移除订阅，false=在组件卸载时自动移除（通过组件的 onScopeDispose 实现）
 * @param onCleanup 函数，移除时回调
 * @returns 函数，用于移除订阅
 */
export function addSubscription<T extends _Method>(
  subscriptions: T[],
  callback: T,
  detached?: boolean,
  onCleanup: () => void = noop
) {
  subscriptions.push(callback)

  const removeSubscription = () => {
    const idx = subscriptions.indexOf(callback)
    if (idx > -1) {
      subscriptions.splice(idx, 1)
      onCleanup()
    }
  }

  if (!detached && getCurrentScope()) {
    onScopeDispose(removeSubscription)
  }

  return removeSubscription
}

/**
 * 发布订阅
 * @param subscriptions 订阅事件回调集合
 * @param args 订阅事件回调参数
 */
export function triggerSubscriptions<T extends _Method>(
  subscriptions: T[],
  ...args: Parameters<T>
) {
  subscriptions.slice().forEach((callback) => {
    callback(...args)
  })
}
